package jrain.fw.http.common.rest.impl;

import java.io.IOException;
import java.util.Enumeration;
import java.util.Map;
import java.util.function.Consumer;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import jrain.fw.core.business.BusinessConst;
import jrain.fw.core.business.BusinessRequest;
import jrain.fw.core.business.BusinessResponse;
import jrain.fw.core.log.Logger;
import jrain.fw.core.log.LoggerFactory;
import jrain.fw.core.utils.FwUtils;
import jrain.fw.http.common.consts.ContentType;
import jrain.utils.lang.LangUtils;
import jrain.utils.lang.StringUtils;

public class BaseAction {

	private static final Logger log = LoggerFactory.getLogger(BaseAction.class);

	public void doAction(BusinessRequest request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) {
		doAction(request, httpRequest, httpResponse, null);
	}

	public void doAction(BusinessRequest request, HttpServletRequest httpRequest, HttpServletResponse httpResponse, Consumer<BusinessRequest> econsumer) {
		try {
			// Cookie 处理
			String tempToken = "";
			Cookie[] cookies = httpRequest.getCookies();
			if (cookies != null) {
				for (Cookie cookie : cookies) {
					if (BusinessConst.DATA_TOKEN.equals(cookie.getName())) {
						tempToken = cookie.getValue();
					}
				}
			}
			String headerToken = httpRequest.getHeader(BusinessConst.DATA_TOKEN);
			if (!StringUtils.isEmpty(headerToken)) {
				tempToken = headerToken;
			}
			String contentType = httpRequest.getHeader(BusinessConst.DATA_CONTENT_TYPE);
			// 参数解析
			String params = StringUtils.trimNull(httpRequest.getParameter(BusinessConst.REQ_PARAMS));
			String paramType = StringUtils.trimNull(httpRequest.getParameter(BusinessConst.REQ_PARAM_TYPE));
			log.trace(request, "params={},paramType={}", paramType, params);

			// 普通参数
			if (StringUtils.isEmpty(paramType)) {
				// 默认参数类型
				if (!StringUtils.isEmpty(params)) {
					Map<String, Object> dataMap = FwUtils.getJsonService().toMap(params);
					request.setData(dataMap);
				} else {
					Enumeration<?> names = httpRequest.getParameterNames();
					while (names.hasMoreElements()) {
						String name = StringUtils.trimNull(names.nextElement());
						Object value = httpRequest.getParameter(name);
						request.putData(name, value);
						log.trace(request, "key={},value={}", name, value);
					}
				}
			} else if (paramType.startsWith(BusinessConst.REQ_PARAM_PRE)) {
				// 前缀参数类型
				String preData = paramType.substring(4);
				int preDataLength = preData.length() + 1;
				Enumeration<?> names = httpRequest.getParameterNames();
				while (names.hasMoreElements()) {
					String name = StringUtils.trimNull(names.nextElement());
					if (name.startsWith(preData + "_") && name.length() >= preDataLength) {
						String key = name.substring(preDataLength);
						Object value = httpRequest.getParameter(name);
						request.putData(key, value);
						log.trace(request, "key={},value={}", key, value);
					}
				}
			}
			// 扩展参数
			final String token = tempToken;
			Consumer<BusinessRequest> consumer = new Consumer<BusinessRequest>() {
				@Override
				public void accept(BusinessRequest t) {
					t.putExtData(BusinessConst.EXT_TOKEN_ID, token);
					t.putExtData(BusinessConst.EXT_REQUEST, httpRequest);
					t.putExtData(BusinessConst.EXT_RESPONSE, httpResponse);
					t.putExtData(BusinessConst.EXT_CONTENT_TYPE, contentType);
					if (econsumer != null) {
						econsumer.accept(t);
					}
				}
			};
			// 响应数据格式
			BusinessResponse response = FwUtils.getBusinessApiClient().doSync(request, consumer);
			String rsContentType = StringUtils.trimNull(response.getExtData(BusinessConst.RS_CONTENT_TYPE));
			if (StringUtils.isEmpty(rsContentType)) {
				httpResponse.setContentType(ContentType.APPLICATION_JSON_UTF8);
			} else {
				httpResponse.setContentType(rsContentType);
			}
			boolean dataEmpty = LangUtils.parseBoolean(response.getExtData(BusinessConst.RS_CONTENT_DATA_EMPTY));
			// 响应数据是否JSON
			if (!dataEmpty) {
				writeData(request, response, httpRequest, httpResponse);
			}
		} catch (Throwable t) {
			write500(request, httpRequest, httpResponse, t);
		}
	}

	protected void writeData(BusinessRequest request, BusinessResponse response, HttpServletRequest httpRequest, HttpServletResponse httpResponse) {
		String data = FwUtils.getJsonService().toPageJson(response);
		write(request, httpResponse, data);
	}

	protected void write500(BusinessRequest request, HttpServletRequest httpRequest, HttpServletResponse httpResponse, Throwable t) {
		String url = httpRequest.getRequestURI();
		log.warn(request, "500 url=" + url, t);
		write(request, httpResponse, "{\"code\":500,\"msg\":\"" + t.getMessage() + "\"}");
	}

	protected void write404(HttpServletRequest httpRequest, HttpServletResponse httpResponse) {
		log.warn(BusinessConst.LOG_BOOT_REQUEST, "404 url={}", httpRequest.getRequestURI());
		write(BusinessConst.LOG_BOOT_REQUEST, httpResponse, "{\"code\":404}");
	}

	protected void write(BusinessRequest request, HttpServletResponse response, String data) {
		try {
			if (!StringUtils.isEmpty(data)) {
				response.getWriter().write(data);
			}
		} catch (IOException e) {
			log.error(request, e.getMessage(), e);
		}
	}

}
